package net.i_tatami.slab.mazesearch.demo;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JFrame;

import net.i_tatami.slab.mazesearch.agent.PledgeMario;
import net.i_tatami.slab.mazesearch.maze.Maze;
import net.i_tatami.slab.mazesearch.maze.VirtualWall;

public class SMarioDemo extends JFrame implements ActionListener, MouseListener{



	private static final int cellSize = 32;



	private boolean isGoalMoving = false;



	private static final long serialVersionUID = 1L;



	private JPanel jContentPane = null;



	private JButton stepButton = null;  //  @jve:decl-index=0:visual-constraint="210,263"



	private JLabel leftSensorInfo = null;



	private JLabel centerSensorInfo = null;



	private JLabel rightSensorInfo = null;



	private Viewer viewer = null;



	private PledgeMario mario;



	private Maze meiro;



	/**

	 * This is the default constructor

	 */

	public SMarioDemo() {

		super();

		initialize();

	}

	public static void main(String[] args) {
		SMarioDemo demo = new SMarioDemo();
		demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        demo.setVisible(true);
	}

	/**

	 * This method initializes this

	 * 

	 * @return void

	 */

	private void initialize() {

		this.setSize(368, 480);

		this.meiro = new Maze();

		this.mario = new PledgeMario(meiro);

		this.setContentPane(getJContentPane());

		this.setTitle("SMarioDemo");

	}



	/**

	 * This method initializes jContentPane

	 * 

	 * @return javax.swing.JPanel

	 */

	private JPanel getJContentPane() {

		if (jContentPane == null) {

			jContentPane = new JPanel();

			jContentPane.setLayout(new BoxLayout(jContentPane, BoxLayout.Y_AXIS));

			jContentPane.add(getViewer());

			jContentPane.add(getLeftSensorInfo());

			jContentPane.add(getCenterSensorInfo());

			jContentPane.add(getRightSensorInfo());

			jContentPane.add(getStepButton());

		}

		return jContentPane;

	}



	private Viewer getViewer(){

		if(viewer == null){

			viewer = new Viewer();

			viewer.addMouseListener(this);

			viewer.setPreferredSize(new Dimension(meiro.getWidth()*cellSize, meiro.getHeight()*cellSize));

			viewer.setAlignmentX(0.5f);



		}

		return viewer;

	}



	/**

	 * This method initializes stepButton	

	 * 	

	 * @return javax.swing.JButton	

	 */

	private JButton getStepButton() {

		if (stepButton == null) {

			stepButton = new JButton("step");

			stepButton.addActionListener(this);

			stepButton.setAlignmentX(0.5f);

		}

		return stepButton;

	}



	private JLabel getLeftSensorInfo() {

		if (leftSensorInfo == null) {

			leftSensorInfo = new JLabel("LeftSensor's info is : "+this.mario.getLeftSensorInfo());

			leftSensorInfo.setAlignmentX(0.5f);

		}

		return leftSensorInfo;

	}



	private JLabel getCenterSensorInfo() {

		if (centerSensorInfo == null) {

			centerSensorInfo = new JLabel("FrontSensor's info is : "+this.mario.getFrontSensorInfo());

			centerSensorInfo.setAlignmentX(0.5f);

		}

		return centerSensorInfo;

	}



	private JLabel getRightSensorInfo() {

		if (rightSensorInfo == null) {

			rightSensorInfo = new JLabel("RightSensor's info is : "+this.mario.getRightSensorInfo());

			rightSensorInfo.setAlignmentX(0.5f);

		}

		return rightSensorInfo;

	}



	private class Viewer extends JPanel{

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;



		public Viewer(){

			this.setAlignmentX(0.5f);

		}



		public void paintComponent(Graphics g){

			ImageIcon road = new ImageIcon("./road.jpg");

			ImageIcon block = new ImageIcon("./block.jpg");

			ImageIcon goal = new ImageIcon("./goal.jpg");
			
			ImageIcon goal_moving = new ImageIcon("./goal_moving.jpg");

			ImageIcon path = new ImageIcon("./path.jpg");


			int imgWidth = road.getIconWidth();

			int imgHeight = road.getIconHeight();

			for(int i = 0 ; i<meiro.getWidth() ; i++){

				for(int j = 0 ; j<meiro.getHeight() ; j++){

					if(meiro.getCircumstance(i, j) == Maze.ROAD){

						g.drawImage(road.getImage(), i*imgWidth, j*imgHeight, imgWidth, imgHeight, null);

					}

					else if(meiro.getCircumstance(i, j) == Maze.WALL){

						g.drawImage(block.getImage(), i*imgWidth, j*imgHeight, imgWidth, imgHeight, null);

					}

					if(meiro.getGoal().x == i && meiro.getGoal().y == j){
						if(isGoalMoving){
							g.drawImage(goal_moving.getImage(), i*imgWidth, j*imgHeight, imgWidth, imgHeight, null);
						}
						else{
							g.drawImage(goal.getImage(), i*imgWidth, j*imgHeight, imgWidth, imgHeight, null);
						}
					}
				}

			}

			for(Point point : mario.getPath()){
				g.drawImage(path.getImage(), point.x*imgWidth, point.y*imgHeight, imgWidth, imgHeight, null);
			}

			switch(mario.getDirection()){

			case Maze.NORTH:
				if(mario.getPath().contains(mario.getLocation())){
					g.drawImage(new ImageIcon("./northOnPath.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				else{
					g.drawImage(new ImageIcon("./up.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				break;

			case Maze.SOUTH:
				if(mario.getPath().contains(mario.getLocation())){
					g.drawImage(new ImageIcon("./southOnPath.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				else{
					g.drawImage(new ImageIcon("./down.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				break;

			case Maze.WEST:
				if(mario.getPath().contains(mario.getLocation())){
					g.drawImage(new ImageIcon("./westOnPath.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				else{
					g.drawImage(new ImageIcon("./left.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				break;

			case Maze.EAST:
				if(mario.getPath().contains(mario.getLocation())){
					g.drawImage(new ImageIcon("./eastOnPath.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				else{
					g.drawImage(new ImageIcon("./right.jpg").getImage(), mario.getLocation().x*imgWidth, mario.getLocation().y*imgHeight, imgWidth, imgHeight, null);
				}
				break;

			}

			g.setColor(Color.black);
			int dx;
			int dy;
			for(VirtualWall vWall : mario.getVWalls()){
				dx = vWall.getNext().x - vWall.getFrom().x;
				dy = vWall.getNext().y - vWall.getFrom().y;
				if(dx == 0 && dy == 1){
					g.drawLine(vWall.getFrom().x*cellSize, (vWall.getFrom().y+1)*cellSize, (vWall.getFrom().x+1)*cellSize, (vWall.getFrom().y+1)*cellSize);
				}
				else if(dx == 0 && dy == -1){
					g.drawLine(vWall.getFrom().x*cellSize, vWall.getFrom().y*cellSize, (vWall.getFrom().x+1)*cellSize, vWall.getFrom().y*cellSize);
				}
				else if(dx == 1 && dy == 0){
					g.drawLine((vWall.getFrom().x+1)*cellSize, vWall.getFrom().y*cellSize, (vWall.getFrom().x+1)*cellSize, (vWall.getFrom().y+1)*cellSize);
				}
				else if(dx == -1 && dy == 0){
					g.drawLine(vWall.getFrom().x*cellSize, vWall.getFrom().y*cellSize, vWall.getFrom().x*cellSize, (vWall.getFrom().y+1)*cellSize);
				}
			}
		}

	}



	public void actionPerformed(ActionEvent e) {

		if(mario.getLocation().equals(meiro.getGoal())){
			this.initialize();
		}
		else{
			this.mario.step();

			this.mario.sense();

			this.getLeftSensorInfo().setText("LeftSensor's info is : "+this.mario.getLeftSensorInfo());

			this.getCenterSensorInfo().setText("FrontSensor's info is : "+this.mario.getFrontSensorInfo());

			this.getRightSensorInfo().setText("RightSensor's info is : "+this.mario.getRightSensorInfo());

			this.getViewer().repaint();
		}


	}



	public void mouseClicked(MouseEvent e) {

		int x = e.getX() / cellSize;

		int y = e.getY() / cellSize;
		
		if(x==0 || x==meiro.getWidth()-1 || y==0 || y==meiro.getHeight()-1){
			return;
		}

		if(isGoalMoving){

			switch(this.meiro.getCircumstance(x, y)){

			case Maze.ROAD:

				meiro.setGoal(new Point(x, y));

				isGoalMoving = false;

				break;

			case Maze.WALL:

				break;

			}

		}

		else{

			if(x == this.meiro.getGoal().x && y == this.meiro.getGoal().y){
				this.isGoalMoving = true;
			}

			else{

				switch(this.meiro.getCircumstance(x, y)){

				case Maze.ROAD:

					this.meiro.setCircumstance(x, y, Maze.WALL);

					break;

				case Maze.WALL:

					this.meiro.setCircumstance(x, y, Maze.ROAD);

					break;

				}

			}      

		}

		this.mario.sense();

		getViewer().repaint();

	}



	public void mouseEntered(MouseEvent e) {

		// TODO Auto-generated method stub



	}



	public void mouseExited(MouseEvent e) {

		// TODO Auto-generated method stub



	}



	public void mousePressed(MouseEvent e) {

		// TODO Auto-generated method stub



	}



	public void mouseReleased(MouseEvent e) {

		// TODO Auto-generated method stub



	}

}  //  @jve:decl-index=0:visual-constraint="7,27"
